package com.ybl.store.backend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ybl.store.backend.dao.entity.CustomerDO;
import com.ybl.store.backend.dao.mapper.ClerkMapper;
import com.ybl.store.backend.dao.mapper.CustomerMapper;
import com.ybl.store.backend.dto.UserInfoDTO;
import com.ybl.store.backend.dto.req.CustomerSaveReqDTO;
import com.ybl.store.backend.dto.req.CustomerUpdateReqDTO;
import com.ybl.store.backend.dto.resp.CustomerRealNameRespDTO;
import com.ybl.store.backend.dto.resp.ListRespDTO;
import com.ybl.store.backend.service.CustomerService;
import com.ybl.store.common.constant.DelFlag;
import com.ybl.store.common.constant.UserIdentity;
import com.ybl.store.common.context.UserContext;
import com.ybl.store.common.convention.errorcode.BaseErrorCode;
import com.ybl.store.common.convention.exception.ClientException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, CustomerDO> implements CustomerService {

    private final ClerkMapper clerkMapper;

    @Override
    public void saveCustomer(CustomerSaveReqDTO requestParam) {
        isAuthorized(requestParam.getClerkId());

        if (clerkMapper.selectById(requestParam.getClerkId()) == null) {
            throw new ClientException(BaseErrorCode.CLERK_NULL_ERROR);
        }

        int result = baseMapper.insert(BeanUtil.toBean(requestParam, CustomerDO.class));

        if (result < 1) {
            throw new ClientException(BaseErrorCode.CUSTOMER_SAVE_ERROR);
        }
    }

    @Override
    public void deleteCustomerById(Long id) {
        CustomerDO customerDO = baseMapper.selectById(id);

        if (customerDO == null) {
            throw new ClientException(BaseErrorCode.CUSTOMER_NULL_ERROR);
        }

        isAuthorized(customerDO.getClerkId());

        int result = baseMapper.deleteById(id);

        if (result < 1) {
            throw new ClientException(BaseErrorCode.CUSTOMER_DELETE_ERROR);
        }
    }

    @Override
    public void updateCustomer(CustomerUpdateReqDTO requestParam) {
        isAuthorized(requestParam.getClerkId());

        if (clerkMapper.selectById(requestParam.getClerkId()) == null) {
            throw new ClientException(BaseErrorCode.CLERK_NULL_ERROR);
        }

        int result = baseMapper.updateById(BeanUtil.toBean(requestParam, CustomerDO.class));

        if (result < 1) {
            throw new ClientException(BaseErrorCode.CUSTOMER_UPDATE_ERROR);
        }
    }

    @Override
    public ListRespDTO<CustomerDO> pageCustomer(Integer pn, Integer ps, Long clerkId, String realName) {
        isAuthorized(clerkId);

        if (clerkId == null) {
            UserInfoDTO userInfoDTO = UserContext.get();

            if (Objects.equals(userInfoDTO.getIdentity(), UserIdentity.clerk)) {
                clerkId = userInfoDTO.getId();
            }
        }

        Page<CustomerDO> page = new Page<>(pn, ps);
        LambdaQueryWrapper<CustomerDO> lambdaQueryWrapper = Wrappers.lambdaQuery(CustomerDO.class)
                .eq(Objects.nonNull(clerkId), CustomerDO::getClerkId, clerkId)
                .like(Objects.nonNull(realName), CustomerDO::getRealName, realName)
                .eq(CustomerDO::getDelFlag, DelFlag.present);
        Page<CustomerDO> customerDOPage = baseMapper.selectPage(page, lambdaQueryWrapper);

        return ListRespDTO
                .<CustomerDO>builder()
                .total(customerDOPage.getTotal())
                .items(customerDOPage.getRecords())
                .build();
    }

    @Override
    public ListRespDTO<CustomerRealNameRespDTO> listCustomerRealName(Long clerkId) {
        isAuthorized(clerkId);

        if (clerkId == null) {
            UserInfoDTO userInfoDTO = UserContext.get();

            if (Objects.equals(userInfoDTO.getIdentity(), UserIdentity.clerk)) {
                clerkId = userInfoDTO.getId();
            }
        }

        LambdaQueryWrapper<CustomerDO> lambdaQueryWrapper = Wrappers.lambdaQuery(CustomerDO.class)
                .eq(Objects.nonNull(clerkId), CustomerDO::getClerkId, clerkId)
                .eq(CustomerDO::getDelFlag, DelFlag.present);
        List<CustomerDO> customerDOList = baseMapper.selectList(lambdaQueryWrapper);

        return ListRespDTO
                .<CustomerRealNameRespDTO>builder()
                .total((long) customerDOList.size())
                .items(customerDOList
                        .stream()
                        .map(each -> BeanUtil.toBean(each, CustomerRealNameRespDTO.class))
                        .toList())
                .build();
    }

    /**
     * 判断同级调用是否有权限
     *
     * @param clerkId 店员 id
     */
    private void isAuthorized(Long clerkId) {
        UserInfoDTO userInfoDTO = UserContext.get();

        if (clerkId != null
                && Objects.equals(userInfoDTO.getIdentity(), UserIdentity.clerk)
                && !Objects.equals(userInfoDTO.getId(), clerkId))
        {
            throw new ClientException(BaseErrorCode.CLIENT_UNAUTHORIZED_ERROR);
        }
    }
}
